/////////////////////////////////////////////////////////////////////////////
// Name:        mdi.cpp
// Purpose:     MDI sample
// Author:      ray1944 
// Modified by:
// Created:     01/14/2012
// Copyright:   ray1944
/////////////////////////////////////////////////////////////////////////////

// ===========================================================================
// declarations
// ===========================================================================

// ---------------------------------------------------------------------------
// headers
// ---------------------------------------------------------------------------

// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"

#ifdef __BORLANDC__
    #pragma hdrstop
#endif

#ifndef WX_PRECOMP
    #include "wx/wx.h"
    #include "wx/mdi.h"
#endif

#include "wx/toolbar.h"
#include "wx/grid.h"
#include "wx/dialog.h"
#include "wx/spinctrl.h"
#include "wx/stattext.h"

#if !defined(__WXMSW__)
    #include "bitmaps/sample.xpm"
    #include "bitmaps/chart.xpm"
#endif

#include "bitmaps/new.xpm"
#include "bitmaps/open.xpm"
#include "bitmaps/save.xpm"
#include "bitmaps/copy.xpm"
#include "bitmaps/cut.xpm"
#include "bitmaps/paste.xpm"
#include "bitmaps/print.xpm"
#include "bitmaps/help.xpm"

#include <sqlite3.h>
#include <sqlite3util.h>
#include "dbi.h"
#include "mdi.h"
#include <Configuration.h>

//linux header include
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
#include <iostream>
#include <vector>

IMPLEMENT_APP(BtsApp)

ConfigurationTable gConfig("/etc/OpenBTS/OpenBTS.db");

// ---------------------------------------------------------------------------
// global variables
// ---------------------------------------------------------------------------

MainFrame *gPtrframe = (MainFrame *) NULL;
wxList my_children;
//IMSI list was saved in TMSITable, short number was saved in sip_buddies
IMSITable gIMSITable(gConfig.getStr("Control.Reporting.TMSITable").c_str());
SingleColDBI gSIPBuddies(gConfig.getStr("SubscriberRegistry.db").c_str());

// For drawing lines in a canvas
//static long xpos = -1;
//static long ypos = -1;

int gs_nFrames = 0;

// ---------------------------------------------------------------------------
// event tables
// ---------------------------------------------------------------------------

BEGIN_EVENT_TABLE(MainFrame, wxMDIParentFrame)
    EVT_MENU(MDI_ABOUT, MainFrame::OnAbout)
    EVT_MENU(MDI_VIEW_IMSI, MainFrame::OnNewIMSIWindow)
    EVT_MENU(MDI_QUIT, MainFrame::OnQuit)
    EVT_MENU(MDI_GSM_OPTS, MainFrame::OnGsmOpt)
    EVT_MENU(MDI_WELCOMEMSG_OPTS, MainFrame::OnWelcomeMsgOpt)
    //EVT_MENU(MDI_LANG_CHN, MainFrame::OnLangChgCh)
    //EVT_MENU(MDI_LANG_ENG, MainFrame::OnLangChgEn)

    EVT_CLOSE(MainFrame::OnClose)
    EVT_SIZE(MainFrame::OnSize)
    EVT_ACTIVATE(MainFrame::OnAct)
END_EVENT_TABLE()

// ===========================================================================
// implementation
// ===========================================================================
//startup all relative process
const char* btsPath = "./OpenBTS";
pid_t gBTSPid = 0;
const char* sipPath = "./sipauthserve";
pid_t gSipPid = 0;
const char* smqPath = "./smqueue";
pid_t gSmqPid = 0;
void startSipProcess()
{
    std::cerr<<"starting sipauthserve"<<sipPath<<std::endl;
    gSipPid = vfork();
    if(gSipPid == 0)
    {
        execlp(sipPath, NULL);
        std::cerr<<"cannot find "<<sipPath<<std::endl;
        _exit(1);
    }
}
void startSmqProcess()
{
    std::cerr<<"starting smqueue"<<smqPath<<std::endl;
    gSmqPid = vfork();
    if(gSmqPid == 0)
    {
        execlp(smqPath, NULL);
        std::cerr<<"cannot find "<<smqPath<<std::endl;
        _exit(1);
    }
}
void startBtsProcess()
{
    //TODO: the function should be locked until bts is OK
    std::cerr<<"starting Bts "<<btsPath<<std::endl;
    gBTSPid = vfork();
    if(gBTSPid == 0)
    {
        execlp(btsPath, NULL);
        std::cerr<<"cannot find"<<btsPath<<std::endl;
        _exit(1);
    }
}

// ---------------------------------------------------------------------------
// BtsApp
// ---------------------------------------------------------------------------
//Initial MainFrame menubar
void BtsApp::InitMenu()
{
    // Make a menubar
    wxMenu *file_menu = new wxMenu;

    //file_menu->Append(MDI_NEW_WINDOW, _("&New window\tCtrl-N"), _("Create a new child window"));
    file_menu->Append(MDI_QUIT, _("&Exit\tAlt-X"), _("Quit the program"));

    wxMenu *help_menu = new wxMenu;
    help_menu->Append(MDI_ABOUT, _("&About\tF1"));

    wxMenu *options_menu = new wxMenu;
    //wxMenu *lang_menu = new wxMenu;
    //lang_menu->Append(MDI_LANG_CHN, _("&Chinese"), _("Display Chinese"));
    //lang_menu->Append(MDI_LANG_ENG, _("&English"), _("Display English"));
    //options_menu->AppendSubMenu(lang_menu, _("&Languages"), _("Change display language"));
    options_menu->Append(MDI_GSM_OPTS, _("&GSM option"), _("Bts Options"));
    options_menu->Append(MDI_WELCOMEMSG_OPTS, _("&Welcome Message Option"), _("Welcome Message Setting"));

    wxMenu *views_menu = new wxMenu;
    views_menu->Append(MDI_VIEW_IMSI, _("&IMSI List"), _("Displaying IMSI list"));    

    wxMenuBar *menu_bar = new wxMenuBar;
    menu_bar->Append(file_menu, _("&File"));
    menu_bar->Append(views_menu, _("&Views"));    
    menu_bar->Append(options_menu, _("&Options")); 
    menu_bar->Append(help_menu, _("&Help"));

    // Associate the menu bar with the frame
    gPtrframe->SetMenuBar(menu_bar);
}

// Initialise this in OnInit, not statically
bool BtsApp::OnInit()
{
    system("./rc.bts stop");
    startSmqProcess();
    startSipProcess();
    startBtsProcess();
    //TODO: should be wait for bts start up succeffully, using UDP heart beat is proper
    //initialize locale
    wxString resDir = wxT(".");
    resDir += wxFILE_SEP_PATH;
    resDir += wxT("lang");
    wxLocale::AddCatalogLookupPathPrefix(resDir);
    m_locale = new wxLocale();
    if (m_locale->Init(/*wxLANGUAGE_DEFAULT*/wxLANGUAGE_CHINESE_SIMPLIFIED,
        wxLOCALE_CONV_ENCODING))
    {
        if (!m_locale->AddCatalog(wxT("i18n"))) {
            std::cerr<<"set chinese catalog failed."<<std::endl;
        }
    }
    else
    {
        m_locale->Init(wxLANGUAGE_DEFAULT, wxLOCALE_CONV_ENCODING);
        std::cerr<<"load chinese language resource failed."<<std::endl;
    }

    // Create the main frame window
    gPtrframe = new MainFrame(
        (wxFrame *)NULL, 
        wxID_ANY,
        _("GSM Demo"),
        wxDefaultPosition, 
        wxSize(500, 400),
        wxDEFAULT_FRAME_STYLE | wxHSCROLL | wxVSCROLL);

    // Give it an icon
    gPtrframe->SetIcon(wxICON(sample));

    //Initial menu
    InitMenu();    

#if wxUSE_STATUSBAR
    gPtrframe->CreateStatusBar(2);
#endif // wxUSE_STATUSBAR

    //set mainframe max size
    gPtrframe->CenterOnParent(wxBOTH);
    wxPoint c = gPtrframe->GetPosition();
    wxSize  s = gPtrframe->GetSize();
    wxSize max(c.x * 2 + s.x, c.y * 2 + s.y);
    gPtrframe->SetPosition(wxPoint(0, 0));
    gPtrframe->SetSize(max);
    gPtrframe->Show(true);
    SetTopWindow(gPtrframe);

    return true;
}

int BtsApp::OnExit()
{
    system("./rc.bts stop");
}

// ---------------------------------------------------------------------------
// MainFrame
// ---------------------------------------------------------------------------

// Define my frame constructor
MainFrame::MainFrame(
    wxWindow *parent,
    const wxWindowID id,
    const wxString& title,
    const wxPoint& pos,
    const wxSize& size,
    const long style)
       :wxMDIParentFrame(parent, id, title, pos, size, style), m_textWindow(NULL), m_only1IMSIFrame(0)
{
    /*m_textWindow = new wxTextCtrl(
        this, 
        wxID_ANY, 
        _T("A help window"),
        wxDefaultPosition, 
        wxDefaultSize,
        wxTE_MULTILINE | wxSUNKEN_BORDER);*/
#if wxUSE_TOOLBAR
    CreateToolBar(wxNO_BORDER | wxTB_FLAT | wxTB_HORIZONTAL);
    InitToolBar(GetToolBar());
#endif // wxUSE_TOOLBAR

#if wxUSE_ACCEL
    // Accelerators
    wxAcceleratorEntry entries[3];
    entries[0].Set(wxACCEL_CTRL, (int) 'N', MDI_NEW_WINDOW);
    entries[1].Set(wxACCEL_CTRL, (int) 'X', MDI_QUIT);
    entries[2].Set(wxACCEL_CTRL, (int) 'A', MDI_ABOUT);
    wxAcceleratorTable accel(3, entries);
    SetAcceleratorTable(accel);
#endif // wxUSE_ACCEL
}

void MainFrame::OnClose(wxCloseEvent& event)
{
    if ( event.CanVeto() && (gs_nFrames > 0) )
    {
        wxString msg;
        msg.Printf(_T("%d windows still open, close anyhow?"), gs_nFrames);
        if ( wxMessageBox(msg, _T("Please confirm"),
                          wxICON_QUESTION | wxYES_NO) != wxYES )
        {
            event.Veto();

            return;
        }
    }

    event.Skip();
}

void MainFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
{
    //if (gTransceiverPid) kill(gTransceiverPid, SIGKILL);

    Close();
}

void MainFrame::OnLangChgCh(wxCommandEvent& event)
{
    if (! GetMenuBar()->IsChecked(MDI_LANG_CHN))
    {
        GetMenuBar()->Check(MDI_LANG_ENG, false);
        GetMenuBar()->Check(MDI_LANG_CHN, true);
        GetMenuBar()->Refresh();
        //m_locale.
        BtsApp * appPtr = (BtsApp *)wxTheApp;
        wxLocale * newLocale = new wxLocale();
        if (newLocale->Init(/*wxLANGUAGE_DEFAULT*/wxLANGUAGE_CHINESE_SIMPLIFIED,
        wxLOCALE_CONV_ENCODING))
        {
            if (!newLocale->AddCatalog(wxT("i18n"))) {
                std::cerr<<"set Chinese catalog failed."<<std::endl;
            }
        }
        else
        {
            std::cerr<<"load Chinese language resource failed."<<std::endl;
        }
        appPtr->SetLocale(newLocale);
    }
}

void MainFrame::OnLangChgEn(wxCommandEvent& event)
{
    
}

void MainFrame::OnAbout(wxCommandEvent& WXUNUSED(event) )
{
    (void)wxMessageBox(
        _("GSM Demo 0.1\n"),
        _("About GSM Demo"));
}

void MainFrame::OnAct(wxActivateEvent& event)
{
    if (0 == m_only1IMSIFrame) 
    {
        showIMSIFrame();
        m_only1IMSIFrame++;
    }
}

void MainFrame::OnNewIMSIWindow(wxCommandEvent& event)
{
    showIMSIFrame();
}

void MainFrame::showIMSIFrame()
{
    // Make another frame, containing a canvas
    IMSIChildFrame *subframe = new IMSIChildFrame(gPtrframe, _("IMSI List"));

    wxString title;
    wxString nums;
    title.Printf(_("IMSI List"));
    nums.Printf(_T(" %d"), ++gs_nFrames);
    title.Append(nums);

    subframe->SetTitle(title);
    // Give it an icon
    subframe->SetIcon(wxICON(chart));

#if wxUSE_MENUS
    // Make a menubar
    wxMenu *file_menu = new wxMenu;
    //file_menu->Append(MDI_NEW_WINDOW, _("&New window"));
    file_menu->Append(MDI_CHILD_QUIT, _("&Close child"), _("Close this window"));
    file_menu->Append(MDI_QUIT, _("&Exit"));

    wxMenu *IMSI_menu = new wxMenu;
    IMSI_menu->Append(MDI_CHILD_IMSI_REFRESH, _("&Refresh\tF5"));
    
    wxMenu *options_menu = new wxMenu;
    //wxMenu *lang_menu = new wxMenu;
    //lang_menu->Append(MDI_LANG_CHN, _("&Chinese"), _("Display Chinese"), wxITEM_CHECK);
    //lang_menu->Append(MDI_LANG_ENG, _("&English"), _("Display English"), wxITEM_CHECK);
    //options_menu->AppendSubMenu(lang_menu, _("&Languages"), _("Change display language"));
    options_menu->Append(MDI_GSM_OPTS, _("&GSM option"), _("Bts Options"));
    options_menu->Append(MDI_WELCOMEMSG_OPTS, _("&Welcome Message Option"), _("Welcome Message Setting"));

    wxMenu *help_menu = new wxMenu;
    help_menu->Append(MDI_ABOUT, _("&About"));

    wxMenuBar *menu_bar = new wxMenuBar;

    menu_bar->Append(file_menu, _("&File"));
    menu_bar->Append(IMSI_menu, _("IMSI List"));
    menu_bar->Append(options_menu, _("&Options"));
    menu_bar->Append(help_menu, _("&Help"));

    // Associate the menu bar with the frame
    subframe->SetMenuBar(menu_bar);
#endif // wxUSE_MENUS

#if wxUSE_STATUSBAR
    subframe->CreateStatusBar();
    subframe->SetStatusText(title);
#endif // wxUSE_STATUSBAR

    int width, height;
    subframe->GetClientSize(&width, &height);
    wxBoxSizer *topSizer = new wxBoxSizer(wxVERTICAL);
    wxGrid * pGrid = new wxGrid(subframe, wxID_ANY);
    pGrid->EnableEditing(false);
    pGrid->SetSelectionMode( wxGrid::wxGridSelectRows );
    subframe->SetGrid(pGrid);
    topSizer->Add(pGrid, 1, wxEXPAND | wxALL, 10);
    wxBoxSizer *buttonSizer = new wxBoxSizer(wxHORIZONTAL);
    buttonSizer->Add(
        new wxButton(subframe, MDI_CHILD_BUT_REFRESH, _("Refresh")),
        0,
        wxALL,
        30);
    buttonSizer->Add(
        new wxButton(subframe, MDI_CHILD_BUT_DEL, _("Delete")),
        0,
        wxALL,
        30);
    topSizer->Add(
        buttonSizer,
        0,
        wxALIGN_CENTER);
    subframe->SetSizer(topSizer);
    topSizer->Fit(subframe);
    topSizer->SetSizeHints(subframe);

    subframe->SetSize(
        this->GetClientSize().GetWidth() * 0.7, 
        this->GetClientSize().GetHeight() * 0.7);
    subframe->CenterOnParent(wxBOTH);
    subframe->Show(true);
}

void MainFrame::OnGsmOpt(wxCommandEvent& event)
{
    //display a module dialog to help user to config BTS
    AdminDialog admindlg(this);
    admindlg.CentreOnParent();
    if (admindlg.ShowModal() == AdminDialog::PWDOK) 
    {
        GsmModalDialog dlg(this);
        dlg.CentreOnParent();
        dlg.ShowModal();
    }
}

void MainFrame::OnWelcomeMsgOpt(wxCommandEvent& event)
{
    WelcomeMsgModalDialog dlg(this);
    dlg.CentreOnParent();
    dlg.ShowModal();
}

void MainFrame::OnSize(
    wxSizeEvent&
#ifdef __WXUNIVERSAL__
    event
#else
    WXUNUSED(event)
#endif
    )
{
    int w, h;
    GetClientSize(&w, &h);

    if (m_textWindow != NULL)
    {
        m_textWindow->SetSize(0, 0, 200, h);
    }
    //GetClientWindow()->SetSize(200, 0, w - 200, h);
    GetClientWindow()->SetSize(0, 0, w, h);

    // FIXME: On wxX11, we need the MDI frame to process this
    // event, but on other platforms this should not
    // be done.
#ifdef __WXUNIVERSAL__
    event.Skip();
#endif
}

#if wxUSE_TOOLBAR
void MainFrame::InitToolBar(wxToolBar* toolBar)
{
    wxBitmap bitmaps[8];

    bitmaps[0] = wxBitmap( new_xpm );
    bitmaps[1] = wxBitmap( open_xpm );
    bitmaps[2] = wxBitmap( save_xpm );
    bitmaps[3] = wxBitmap( copy_xpm );
    bitmaps[4] = wxBitmap( cut_xpm );
    bitmaps[5] = wxBitmap( paste_xpm );
    bitmaps[6] = wxBitmap( print_xpm );
    bitmaps[7] = wxBitmap( help_xpm );

    toolBar->AddTool(MDI_NEW_WINDOW, _T("New"), bitmaps[0], _T("New file"));
    toolBar->AddTool(1, _T("Open"), bitmaps[1], _T("Open file"));
    toolBar->AddTool(2, _T("Save"), bitmaps[2], _T("Save file"));
    toolBar->AddSeparator();
    toolBar->AddTool(3, _T("Copy"), bitmaps[3], _T("Copy"));
    toolBar->AddTool(4, _T("Cut"), bitmaps[4], _T("Cut"));
    toolBar->AddTool(5, _T("Paste"), bitmaps[5], _T("Paste"));
    toolBar->AddSeparator();
    toolBar->AddTool(6, _T("Print"), bitmaps[6], _T("Print"));
    toolBar->AddSeparator();
    toolBar->AddTool(MDI_ABOUT, _T("About"), bitmaps[7], _T("Help"));

    toolBar->Realize();
}
#endif // wxUSE_TOOLBAR
